"""
AI模型服务接口
"""
import asyncio
import logging
import time
from abc import ABC, abstractmethod
from typing import Dict, Any, Optional, List
import openai

from backend.utils.config import config
from backend.models.core import ExecutionResult

logger = logging.getLogger(__name__)


class AIModelService(ABC):
    """AI模型服务基类"""
    
    @abstractmethod
    async def generate_text(self, prompt: str, **kwargs) -> ExecutionResult:
        """生成文本"""
        pass
    
    @abstractmethod
    async def chat_completion(self, messages: List[Dict[str, str]], **kwargs) -> ExecutionResult:
        """聊天补全"""
        pass


class OpenAIService(AIModelService):
    """OpenAI API服务实现"""
    
    def __init__(self):
        self.client = openai.AsyncOpenAI(
            api_key=config.ai_model.api_key,
            base_url=config.ai_model.api_base
        )
        self.model = config.ai_model.model
        self.max_tokens = config.ai_model.max_tokens
        self.temperature = config.ai_model.temperature
        self.timeout = config.ai_model.timeout
        self.max_retries = config.ai_model.max_retries
    
    async def generate_text(self, prompt: str, **kwargs) -> ExecutionResult:
        """生成文本"""
        messages = [{"role": "user", "content": prompt}]
        return await self.chat_completion(messages, **kwargs)
    
    async def chat_completion(self, messages: List[Dict[str, str]], **kwargs) -> ExecutionResult:
        """聊天补全"""
        start_time = time.time()
        
        # 合并参数
        params = {
            'model': kwargs.get('model', self.model),
            'messages': messages,
            'max_tokens': kwargs.get('max_tokens', self.max_tokens),
            'temperature': kwargs.get('temperature', self.temperature),
            'timeout': kwargs.get('timeout', self.timeout)
        }
        
        for attempt in range(self.max_retries):
            try:
                logger.debug(f"AI API call attempt {attempt + 1}/{self.max_retries}")
                
                response = await self.client.chat.completions.create(**params)
                
                execution_time = time.time() - start_time
                tokens_used = response.usage.total_tokens if response.usage else 0
                content = response.choices[0].message.content
                
                logger.info(f"AI API call successful, tokens: {tokens_used}, time: {execution_time:.2f}s")
                
                return ExecutionResult(
                    success=True,
                    result=content,
                    tokens_used=tokens_used,
                    execution_time=execution_time,
                    metadata={
                        'model': params['model'],
                        'attempt': attempt + 1
                    }
                )
                
            except openai.RateLimitError as e:
                logger.warning(f"Rate limit error on attempt {attempt + 1}: {e}")
                if attempt < self.max_retries - 1:
                    wait_time = 2 ** attempt  # 指数退避
                    await asyncio.sleep(wait_time)
                    continue
                break
                
            except openai.APITimeoutError as e:
                logger.warning(f"Timeout error on attempt {attempt + 1}: {e}")
                if attempt < self.max_retries - 1:
                    await asyncio.sleep(1)
                    continue
                break
                
            except openai.APIError as e:
                logger.error(f"API error on attempt {attempt + 1}: {e}")
                if attempt < self.max_retries - 1:
                    await asyncio.sleep(1)
                    continue
                break
                
            except Exception as e:
                logger.error(f"Unexpected error on attempt {attempt + 1}: {e}")
                break
        
        execution_time = time.time() - start_time
        return ExecutionResult(
            success=False,
            error=f"Failed after {self.max_retries} attempts",
            execution_time=execution_time
        )
    
    async def validate_connection(self) -> bool:
        """验证连接"""
        try:
            result = await self.generate_text("Test connection", max_tokens=10)
            return result.success
        except Exception as e:
            logger.error(f"Connection validation failed: {e}")
            return False


# 全局AI服务实例
ai_service = None

def get_ai_service():
    """获取AI服务实例"""
    global ai_service
    if ai_service is None:
        ai_service = OpenAIService()
    return ai_service